<?php


namespace seecms\lib\builder\control;

use ArrayAccess;

abstract class Control implements ArrayAccess
{
    /**
     * @var string
     */
    protected $type = 'text';

    /**
     * @var string
     */
    protected $name = '';

    /**
     * @var string
     */
    protected $label = '';

    /**
     * @var string
     */
    protected $placeholder = '';

    /**
     * @var bool
     */
    protected $required = true;

    /**
     * @var bool
     */
    protected $readonly = false;

    /**
     * @var bool
     */
    protected $disabled = false;

    /**
     * @var array|string
     */
    protected $description = '';

    /**
     * @var array
     */
    protected $options = [];

    /**
     * @var string|array|int|null
     */
    protected $value = null;

    /**
     * @var array
     */
    protected $remote = [];

    /**
     * @var string
     */
    protected $prefix = '';

    /**
     * @var string
     */
    protected $suffix = '';

    /**
     * 行内元素
     * @var bool|string
     */
    protected $inline = '';

    /**
     * 渲染
     * @return string
     */
    abstract public function render(): string;

    public function offsetSet($offset, $value)
    {
        $this->$offset = $value;
    }

    public function offsetExists($offset)
    {
        return isset($this->$offset);
    }

    public function offsetGet($offset)
    {
        if ($offset === 'description') {
            return $this->getDescription();
        }
        return $this->$offset ?? null;
    }

    public function offsetUnset($offset)
    {
        unset($this->$offset);
    }

    /**
     * @param $name
     * @return static
     */
    public static function init($name = null)
    {
        $self = new static();
        $self->name = $name ?: 'region';
        return $self;
    }

    /**
     * @return string
     */
    public function getType(): string
    {
        return $this->type;
    }

    /**
     * @param string $type
     * @return $this
     */
    public function setType(string $type): Control
    {
        $this->type = $type;

        return $this;
    }

    /**
     * @return string
     */
    public function getName(): string
    {
        return $this->name;
    }

    /**
     * @param string $name
     * @return $this
     */
    public function setName(string $name): Control
    {
        $this->name = $name;

        return $this;
    }

    /**
     * @return string
     */
    public function getLabel(): string
    {
        return $this->label;
    }

    /**
     * @param string $label
     * @return $this
     */
    public function setLabel(string $label): Control
    {
        $this->label = $label;

        return $this;
    }

    /**
     * @return string
     */
    public function getPlaceholder(): string
    {
        $placeholder = $this->placeholder;
        if (empty($placeholder)) {
            $prefix = '请输入';
            if ($this->type === 'select') {
                $prefix = '请选择';
            }
            $placeholder = $prefix . $this->getLabel();
        }

        return $placeholder;
    }

    /**
     * @param string $placeholder
     * @return $this
     */
    public function setPlaceholder(string $placeholder): Control
    {
        $this->placeholder = $placeholder;

        return $this;
    }

    /**
     * @return bool
     */
    public function isRequired(): bool
    {
        return $this->required;
    }

    /**
     * @param bool $required
     * @return $this
     */
    public function setRequired(bool $required = false): Control
    {
        $this->required = $required;

        return $this;
    }

    /**
     * @return bool
     */
    public function isReadonly(): bool
    {
        return $this->readonly;
    }

    /**
     * @param bool $readonly
     * @return $this
     */
    public function setReadonly(bool $readonly = true): Control
    {
        $this->readonly = $readonly;

        return $this;
    }

    /**
     * @return bool
     */
    public function isDisabled(): bool
    {
        return $this->disabled;
    }

    /**
     * @param bool $disabled
     * @return $this
     */
    public function setDisabled(bool $disabled = true): Control
    {
        $this->disabled = $disabled;

        return $this;
    }

    /**
     * @return string
     */
    public function getDescription(): string
    {
        $description = $this->description;
        if (empty($description)) {
            return '';
        }

        if (is_array($description)) {
            $description = implode('<br/>', $description);
        }

        return <<<EOF
<div class="layui-word-aux">
    $description
</div>
EOF;
    }

    /**
     * @param array|string $description
     * @return $this
     */
    public function setDescription($description): Control
    {
        $this->description = $description;

        return $this;
    }

    /**
     * @return array
     */
    public function getOptions(): array
    {
        return $this->options;
    }

    /**
     * @param array $options
     * @return $this
     */
    public function setOptions(array $options): Control
    {
        if ($options) {
            $this->options = $options;
        }

        return $this;
    }

    /**
     * @return array|int|string|null
     */
    public function getValue()
    {
        return $this->value;
    }

    /**
     * @param array|int|string|null $value
     * @return $this
     */
    public function setValue($value): Control
    {
        $this->value = $value;

        return $this;
    }

    public function getPrefix(): string
    {
        return $this->prefix;
    }

    public function setPrefix(string $prefix): Control
    {
        $this->prefix = $prefix;

        return $this;
    }

    public function getSuffix(): string
    {
        return $this->suffix;
    }

    public function setSuffix(string $suffix): Control
    {
        $this->suffix = $suffix;

        return $this;
    }

    public function getInline()
    {
        return $this->inline;
    }

    public function setInline(string $inline = 'inline'): Control
    {
        $this->inline = $inline;

        return $this;

    }
}